/*Z OK */

/*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: GPL-2.0-only
 */

#include <machine/assembler.h>

/*
 * Calling convention for x86-64
 * For integer type, the next available register of the sequence %rdi,
 * %rsi, %rdx, %rcx, %r8 and %r9 are used for passing values. %rax and
 * %rdx are used for returning integer values. Pointers are considered
 * as integer type according to the ABI.
 */

.section .boot.text

.section .text
/*Z 向rdi指明的第一个参数：端口，发送rsi指明的第二个参数：一个字节 */
BEGIN_FUNC(out8)                        # port, value
    movq    %rdi, %rdx
    movq    %rsi, %rax
    outb    %al, %dx
    ret
END_FUNC(out8)
/*Z 向rdi指明的第一个参数：端口，发送rsi指明的第二个参数：两个字节 */
BEGIN_FUNC(out16)
    movq    %rdi, %rdx
    movq    %rsi, %rax
    outw    %ax, %dx
    ret
END_FUNC(out16)
/*Z 向rdi指明的第一个参数：端口，发送rsi指明的第二个参数：四个字节 */
BEGIN_FUNC(out32)
    movq    %rdi, %rdx
    movq    %rsi, %rax
    outl    %eax, %dx
    ret
END_FUNC(out32)
/*Z 从rdi指明的端口读入一个字节，放入rax */
BEGIN_FUNC(in8)
    movq    $0, %rax
    movq    %rdi, %rdx
    inb     %dx, %al
    ret
END_FUNC(in8)
/*Z 从rdi指明的端口读入两个字节，放入rax */
BEGIN_FUNC(in16)
    movq    $0, %rax
    movq    %rdi, %rdx
    inw     %dx, %ax
    ret
END_FUNC(in16)
/*Z 从rdi指明的端口读入四个字节，放入rax */
BEGIN_FUNC(in32)
    movq    $0, %rax
    movq    %rdi, %rdx
    inl     %dx, %eax
    ret
END_FUNC(in32)
/*Z 通过cpuid指令获取cacheline大小（字节），放入到eax中 */
BEGIN_FUNC(getCacheLineSize)
    push    %rbx
    movl    $1, %eax
    cpuid
    movl    %ebx, %eax
    shrl    $8, %eax
    andl    $0xff, %eax
    shll    $3, %eax
    pop     %rbx
    ret
END_FUNC(getCacheLineSize)
/*Z 将参数指明的限长和基地址加载到GDTR寄存器中，DS、ES、SS段均指向GDT_DS_0段描述符，FS、GS段均置0 */
BEGIN_FUNC(x64_install_gdt)
    lgdt    (%rdi)          # load gdtr with gdt pointer
    movw    $0x10, %ax      # load register ax with seg selector
    movw    %ax, %ds        /*Z DS、ES、SS段均指向GDT_DS_0段描述符 */
    movw    %ax, %es
    movw    %ax, %ss
    movw    $0x0, %ax
    movw    %ax, %fs        /*Z FS、GS段均置0 */
    movw    %ax, %gs
    ret
END_FUNC(x64_install_gdt)
/*Z 将参数指明的限长和基地址加载到IDTR寄存器中 */
BEGIN_FUNC(x64_install_idt)
    lidt    (%rdi)
    ret
END_FUNC(x64_install_idt)
/*Z 将参数指明的段选择子（16位偏移量）加载到LDTR寄存器的选择子域，然后cpu自动从GDT中索引得到LDT段基地址和限长 */
BEGIN_FUNC(x64_install_ldt)
    lldt    %di
    ret
END_FUNC(x64_install_ldt)
/*Z 将参数指明的段选择子（16位偏移量）加载到TR寄存器的选择子域，然后cpu自动从GDT中索引得到TSS段基地址和限长 */
BEGIN_FUNC(x64_install_tss)
    ltr     %di
    ret
END_FUNC(x64_install_tss)
